{
	//具备Iterator接口可以直接使用for...of遍历
	let arr=[ 'hello', 'world' ];
	//返回一个具有next()方法的对象 
	let iterator=arr[Symbol.iterator]();
	console.log(iterator.next());// {value: "hello", done: false}
	console.log(iterator.next());// {value: "world", done: false}
	console.log(iterator.next());// {value: undefined, done: true}
	/**
	 * value:表示数组的值,done:是否终止循环
	 */
	for(let value of arr){
		console.log(value);
	}
}
{
	//为对象部署Iterator接口,数组set,map也可以自定义Iterator接口
	let obj = {
	    data: [ 'hello', 'world' ],
	    //自定义Iterator接口
	    [Symbol.iterator]() {
	        const self = this;
	        let index = 0;
	        //必须返回一个含有next()方法的对象
	        return {
	            next() {
	                if (index < self.data.length) {
	                    return {
	                        value: self.data[index++],
	                        done: false
	                    };
	                } else {
	                    return { value: undefined, done: true };
	                }
	            }
	        };
	    }
	};
	//部署后可以进行for of操作
	for(let value of obj){
		console.log(value)//hello  world
	}
}
{
	//Generator的声明方式类似一般的函数声明，只是多了个*号，并且一般可以在函数内看到yield关键字
	let showWords=function* (){
		console.log('1');
		yield 'one';
		console.log('2');
		yield 'two';
		console.log('3');
		return  'three';
	}
	/**
	 * 定义了一个showWords的生成器函数，调用之后返回了一个迭代器对象（即show）
	      调用next方法后，函数内执行第一条yield语句，输出当前的状态done（迭代器是否遍历完成）以及相应值（一般为yield关键字后面的运算结果）
	      每调用一次next，则执行一次yield语句，并在该处暂停，等待下一次next()调用,return完成之后，
	      就退出了生成器函数，后续如果还有yield操作就不再执行了
	 */
	let show=showWords();
	console.log(show.next()); // 1 {value: "one", done: false}
	console.log(show.next()); // 2 {value: "two", done: false}
	console.log(show.next()); // 3 {value: "three", done: true}

}
{
	function* showWords() {
	    yield 'one';
	    //yield只能原封不动地返回右边运算后值
	    yield showNumbers();
	    //showNumbers()不是一般的函数调用，返回的是迭代器对象
        //所以换个yield* 让它自动遍历进该对象
        yield* showNumbers();
	    return 'three';
	}
	function* showNumbers() {
	    yield 10 + 1;
	    yield 12;
	}
	let show = showWords();
	console.log(show.next()) // {done: false, value: "one"}
	console.log(show.next()) // {done: false, value: showNumbers}
	console.log(show.next()) // {done: false, value: 11}
	console.log(show.next()) // {done: false, value: 12}
	console.log(show.next()) // {done: true, value: "three"}
	console.log(show.next()) // {done: true, value: undefined}
	//yield和yield* 只能在generator函数内部使用，一般的函数内使用会报错
}
/*{
	//Genertor的语法糖: 去掉* 前面加async,yeild换成await
	let showWords=async function (){
		console.log('1');
		await 'one';
		console.log('2');
		await 'two';
		console.log('3');
		return  'three';
	}
	//语法糖:与之前写法作用一样,只是写起来更爽美观像吃了糖一样,所以叫语法糖
	let show=showWords();
	console.log(show.next()); // 1 {value: "one", done: false}
	console.log(show.next()); // 2 {value: "two", done: false}
	console.log(show.next()); // 3 {value: "three", done: true}
}*/
/*{
	//抽奖函数
	let draw=function(count){
		//具体抽奖逻辑
		console.log('剩余${count}次')
	}
	
	//定义Genertor函数
	let residue=function* (count){
		while(count>0){
			count--;
			yield draw(count);//每次next()后执行完停止,等待下一次next(),即下一次抽奖
		}
	}
	let start=residue(5);
	let btn=document.createElement('button');
	btn.id='start';
	btn.textContent='抽奖';
	document.body.appendChild(btn);
	document.getElementById('start').addEventListener('click',function(){
		start.next();
	},false);
	//好处:没有将次数存储到变量中,减少内存,增加性能,更加安全,防止别人修改次数
}*/
{
	//长轮询
	//Generator函数
	let ajax=function* (){
		yield new Promise(
			function(resolve,reject){
				setTimeout(function(){
					resolve({code:0});
				},200)
			}
		);
	}
	let pull=function(){
		let generator=ajax();
		// step :返回一个{value:Promise对象,done:boolear}
		let step=generator.next();
		//.then执行resolve
		step.value.then(function(d){
			if(d.code!=0){//如果code不是0,就一直查询
				setTimeout(function(){
					console.log("查询中...");
					pull();
				})
			}else{//是0就输出
				console.log(d);
			}
		})
	}
	pull()
}
{
	function* showNumbers() {
	    var one = yield 1;
	    var two = yield 2 * one;
	    yield 3 * two;
	}
	var show = showNumbers();
	show.next().value // 1
	show.next().value // NaN
	show.next(2).value // 6  传递参数2将上一次返回值two设为2
	/**
	 * 第一次调用next之后返回值one为1，但在第二次调用next的时候one其实是undefined的，
	 * 因为generator不会自动保存相应变量值，我们需要手动的指定，
	 * 这时two值为NaN，在第三次调用next的时候执行到yield 3 * two，通过传参将上次yield返回值two设为2，得到结果
	 */
}
